﻿# coding: UTF-8
# Name: 导数对象
# Author: LYC
# Created: 2014-03-17

import math
from copy import deepcopy
import logging

class Number(float):
    """
    数字类
    """
    def __init__(self, value):
        super(Number, self).__init__(value)

    def __div__(self, n):
        if self.isSupportedType(n):
            logging.debug("%.2f, %.2f", self, n)
            return super(Number, self).__div__(n)

        n = n ** -1
        logging.debug("%.2f, %.2f", n, self)
        return n * self

    def __add__(self, n):
        logging.debug("%.2f, %.2f", self, n)
        if self.isSupportedType(n):
            return Number(self + n)
        else:
            return Number(n + self)

    def __sub__(self, n):
        logging.debug("%.2f, %.2f", self, n)
        if self.isSupportedType(n):
            return Number(self - n)
        else:
            return Number(0 - n + self)

    def __mul__(self, n):
        logging.debug("%.2f, %.2f", self, n)
        if self.isSupportedType(n):
            return Number(self * n)
        else:
            return Number(n * self)

    def isSupportedType(self, obj):
        """
        判断是否是支持的类型
        """
        return type(obj) in [Number]

class Differentiation(Number):
    """
    导数类
    """

    def __init__(self, value, power = 1):
        super(Differentiation, self).__init__(value)

        self.__power = power

    def copy(self, p):
        """
        从当前对象复制
        """
        d = deepcopy(self)
        d.__power = p
        logging.debug("copy %.2f with power %d", d, d.__power)
        return d

    def isSupportedType(self, obj):
        """
        判断是否是支持的类型
        """
        return type(obj) in [Differentiation]

    def __call__(self):
        v = self ** 1
        logging.debug("%.2f ** %.2f = %.2f", self, 1, v)
        return v

    def __str__(self):
        s = str(self())
        logging.debug("value %s", s)
        return s

    def __repr__(self):
        return str(self)

    def __pow__(self, p):
        p = p * self.__power
        r = super(Differentiation, self).__pow__(p - 1) * p
        logging.debug("%.2f ** %.2f = %.2f", self, p, r)
        return r

    def __add__(self, n):
        logging.debug("%.2f, %.2f", self, n)
        return self() + n

    def __sub__(self, n):
        logging.debug("%.2f, %.2f", self, n)
        return self() - n

    def __mul__(self, n):
        if self.isSupportedType(n):
            #处理x*x*x这样的情况
            return self.copy(self.__power + n.__power)

        logging.debug("%.2f, %.2f", self, n)
        return self() * n

    def __div__(self, n):
        if self.isSupportedType(n):
            #处理x/x这样的情况
            return self.copy(self.__power - n.__power)

        logging.debug("%.2f, %.2f", self, n)
        return self() / n

    @classmethod
    def __base(cls, obj, name = ""):
        b_obj = super(cls, obj)
        if name:
            return getattr(b_obj, name, None)
        else:
            return b_obj

E = Number(math.e)
PI = Number(math.pi)